package cn.trinea.android.demo;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import cn.trinea.android.common.entity.FailedReason;
import cn.trinea.android.common.service.impl.FileNameRuleImageUrl;
import cn.trinea.android.common.service.impl.ImageSDCardCache;
import cn.trinea.android.common.service.impl.ImageSDCardCache.OnImageSDCallbackListener;
import cn.trinea.android.common.service.impl.RemoveTypeLastUsedTimeFirst;
import cn.trinea.android.common.util.ListUtils;
import cn.trinea.android.common.view.SlideOnePageGallery;

/**
 * ImageSDCardCacheDemo
 * 
 * @author <a href="http://www.trinea.cn/android/android-imagesdcardcache/" target="_blank">Trinea</a> 2013-6-25
 */
public class ImageSDCardCacheDemo extends BaseActivity {

	public static final String TAG_CACHE = "image_sdcard_cache";
	/** cache folder path which be used when saving images **/
	public static final String DEFAULT_CACHE_FOLDER = new StringBuilder().append(Environment.getExternalStorageDirectory().getAbsolutePath())
			.append(File.separator).append("Trinea").append(File.separator).append("AndroidDemo").append(File.separator).append("ImageSDCardCache")
			.toString();

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState, R.layout.image_sdcard_cache_demo);

		initImageUrlList();
		IMAGE_SD_CACHE.initData(context, TAG_CACHE);
		IMAGE_SD_CACHE.setContext(context);
		IMAGE_SD_CACHE.setCacheFolder(DEFAULT_CACHE_FOLDER);

		SlideOnePageGallery imageGallery = (SlideOnePageGallery) findViewById(R.id.app_app_image_gallery);
		ImageAdapter adapter = new ImageAdapter(context);
		adapter.setImageUrlList(imageUrlList);
		imageGallery.setAdapter(adapter);

	}

	@Override
	protected void onDestroy() {
		IMAGE_SD_CACHE.saveDataToDb(this, TAG_CACHE);
		super.onDestroy();
	}

	/**
	 * if you just want load image for ImageView, just like this, no need to setOnImageSDCallbackListener and so on like <code>static</code> below
	 */
	// public static final ImageSDCardCache IMAGE_SD_CACHE = CacheManager.getImageSDCardCache();

	/** image cache **/
	public static final ImageSDCardCache IMAGE_SD_CACHE = new ImageSDCardCache();

	static {
		/** init image cache **/
		OnImageSDCallbackListener imageCallBack = new OnImageSDCallbackListener() {

			/**
			 * callback function after get image successfully, run on ui thread
			 * 
			 * @param imageUrl
			 *            imageUrl
			 * @param imagePath
			 *            image path
			 * @param view
			 *            view need the image
			 * @param isInCache
			 *            whether already in cache or got realtime
			 */
			@Override
			public void onGetSuccess(String imageUrl, String imagePath, View view, boolean isInCache) {
				ImageView imageView = (ImageView) view;

				// avoid oom caused by bitmap size exceeds VM budget
				BitmapFactory.Options option = new BitmapFactory.Options();
				option.inSampleSize = getImageScale(imagePath);
				Bitmap bm = BitmapFactory.decodeFile(imagePath, option);
				if (bm != null) {
					imageView.setImageBitmap(bm);

					// first time show with animation
					if (!isInCache) {
						imageView.startAnimation(getInAlphaAnimation(2000));
					}
					imageView.setScaleType(ScaleType.FIT_CENTER);
				}
			}

			/**
			 * callback function before get image, run on ui thread
			 * 
			 * @param imageUrl
			 *            imageUrl
			 * @param view
			 *            view need the image
			 */
			@Override
			public void onPreGet(String imageUrl, View view) {
				// Log.e(TAG_CACHE, "pre get image");
			}

			@Override
			public void onGetNotInCache(String imageUrl, View view) {
				// you can do something when image not in cache, for example set default image
				if (view != null && view instanceof ImageView) {
					((ImageView) view).setImageResource(R.drawable.trinea);
					((ImageView) view).setScaleType(ScaleType.CENTER);
				}
			}

			/**
			 * callback function after get image failed, run on ui thread
			 * 
			 * @param imageUrl
			 *            imageUrl
			 * @param imagePath
			 *            image path
			 * @param view
			 *            view need the image
			 * @param failedReason
			 *            failed reason for get image
			 */
			@Override
			public void onGetFailed(String imageUrl, String imagePath, View view, FailedReason failedReason) {
				Log.e(TAG_CACHE,
						new StringBuilder(128).append("get image ").append(imageUrl).append(" error, failed type is: ")
								.append(failedReason.getFailedType()).append(", failed reason is: ").append(failedReason.getCause().getMessage())
								.toString());
			}
		};
		IMAGE_SD_CACHE.setOnImageSDCallbackListener(imageCallBack);
		IMAGE_SD_CACHE.setCacheFullRemoveType(new RemoveTypeLastUsedTimeFirst<String>());
		IMAGE_SD_CACHE.setFileNameRule(new FileNameRuleImageUrl());

		IMAGE_SD_CACHE.setHttpReadTimeOut(10000);
		IMAGE_SD_CACHE.setOpenWaitingQueue(true);
		IMAGE_SD_CACHE.setValidTime(-1);
		/**
		 * close connection, default is connect keep-alive to reuse connection. if image is from different server, you can set this
		 */
		// IMAGE_SD_CACHE.setRequestProperty("Connection", "false");
	}

	public static AlphaAnimation getInAlphaAnimation(long durationMillis) {
		AlphaAnimation inAlphaAnimation = new AlphaAnimation(0, 1);
		inAlphaAnimation.setDuration(durationMillis);
		return inAlphaAnimation;
	}

	/**
	 * scale image to fixed height and weight
	 * 
	 * @param imagePath
	 * @return
	 */
	private static int getImageScale(String imagePath) {
		BitmapFactory.Options option = new BitmapFactory.Options();
		// set inJustDecodeBounds to true, allowing the caller to query the bitmap info without having to allocate the
		// memory for its pixels.
		option.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(imagePath, option);

		int scale = 1;
		while (option.outWidth / scale >= IMAGE_MAX_WIDTH || option.outHeight / scale >= IMAGE_MAX_HEIGHT) {
			scale *= 2;
		}
		return scale;
	}

	private static int IMAGE_MAX_WIDTH = 480;
	private static int IMAGE_MAX_HEIGHT = 960;

	private List<String> imageUrlList;

	private void initImageUrlList() {
		imageUrlList = new ArrayList<String>();
		imageUrlList.add("http://farm4.staticflickr.com/3755/9148527824_6c156185ea.jpg");
		imageUrlList.add("http://farm8.staticflickr.com/7409/9148527822_36fa37d7ca_z.jpg");
		imageUrlList.add("http://farm8.staticflickr.com/7318/9148527808_e804baef0b.jpg");
		imageUrlList.add("http://farm8.staticflickr.com/7318/9146300275_5fe995d123.jpg");
		imageUrlList.add("http://farm8.staticflickr.com/7351/9148527976_8a4e75ae87.jpg");
		imageUrlList.add("http://farm8.staticflickr.com/7288/9146300469_bd3420c75b_z.jpg");
		imageUrlList.add("http://farm3.staticflickr.com/2863/9148527892_31f9377351_o.jpg");
		imageUrlList.add("http://farm3.staticflickr.com/2888/9148527996_f05118d7de_o.jpg");
		imageUrlList.add("http://farm8.staticflickr.com/7310/9148528008_8e8f51997a.jpg");
		imageUrlList.add("http://farm3.staticflickr.com/2849/9148528108_dfcda19507.jpg");
		imageUrlList.add("http://farm4.staticflickr.com/3739/9148528022_e9bf03058f.jpg");
	}

	private static class ImageAdapter extends BaseAdapter {

		private LayoutInflater inflater;
		public List<String> imageUrlList;

		public ImageAdapter(Context context) {
			super();
			inflater = LayoutInflater.from(context);
		}

		@Override
		public int getCount() {
			return ListUtils.isEmpty(imageUrlList) ? 0 : imageUrlList.size();
		}

		@Override
		public Object getItem(int position) {
			return ListUtils.isEmpty(imageUrlList) ? null : imageUrlList.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			if (convertView == null) {
				convertView = inflater.inflate(R.layout.image_list_item, null);
				holder = new ViewHolder();
				holder.imageView = (ImageView) convertView.findViewById(R.id.image_list_image);
				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}

			IMAGE_SD_CACHE.get(imageUrlList.get(position), holder.imageView);
			return convertView;
		}

		public void setImageUrlList(List<String> imageUrlList) {
			this.imageUrlList = imageUrlList;
		}

		/**
		 * ViewHolder
		 * 
		 * @author Trinea 2012-11-22
		 */
		static class ViewHolder {

			ImageView imageView;
		}
	}
}
